package com.laicunba.service.jzh.impl;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.laicunba.pojo.BaseDO;
import com.laicunba.pojo.JzhAccountDO;
import com.laicunba.pojo.JzhBalanceItemDO;
import com.laicunba.pojo.UserBankDO;
import com.laicunba.pojo.UserDO;
import com.laicunba.service.UserBankService;
import com.laicunba.service.UserService;
import com.laicunba.service.impl.BaseServiceImpl;
import com.laicunba.service.jzh.JzhAccountService;
import com.laicunba.service.jzh.JzhBalanceItemService;
import com.laicunba.service.jzh.JzhRegService;
import com.laicunba.util.AssertUtil;
import com.laicunba.util.StringUtil;

@Service
public class JzhAccountServiceImpl extends BaseServiceImpl implements JzhAccountService {
	private static final Logger LOG = Logger.getLogger(JzhAccountServiceImpl.class);
	@Autowired
	private UserService userService;
	@Autowired
	private JzhRegService jzhRegService;
	@Autowired
	private UserBankService userBankService;
	@Autowired
	private JzhBalanceItemService jzhBalanceItemService;

	@Override
	public boolean create(BaseDO entiry) {
		JzhAccountDO accountDO = (JzhAccountDO) entiry;
		accountDO.setBalance(BigDecimal.ZERO);
		return super.create(accountDO);
	}

	@Transactional
	@Override
	public boolean createAccountWithBindCard(String uid, String cityId) {
		AssertUtil.assertNotEmpty(uid, "UID_CANT_EMPTY");
		UserDO userDO = userService.get(UserDO.class, uid);
		AssertUtil.assertNotNull(userDO, "USER_NOT_EXIST");
		JzhAccountDO jzhAccountDO = get(JzhAccountDO.class, userDO.getId());
		AssertUtil.assertTrue(jzhAccountDO == null, "JZH_ACCOUNT_EXIST");
		AssertUtil.assertTrue(StringUtil.isEmpty(userDO.getJzhStatus()), "MAYBE_CREATE_JZH");
		AssertUtil.assertTrue(userService.updateStatus(uid, "no-biz", "正在开通存管中..."), "LOCK_USR_FAIL");
		AssertUtil.assertNotEmpty(userDO.getTrueName(), "NO_TRUE_NAME");
		AssertUtil.assertNotEmpty(userDO.getPid(), "NO_PID");

		List<UserBankDO> userBankList = userBankService.findByUserId(uid);
		AssertUtil.assertTrue(userBankList != null && !userBankList.isEmpty(), "NOT_FOUND_BANK_CARD");
		AssertUtil.assertTrue(userBankList.size() == 1, "FOUND_TOO_MANY_BANK_CARD");

		// 开通金账户
		String orderNo = System.currentTimeMillis() + "";
		String bankCode = userBankList.get(0).getBankCode();
		// 10位为富友银行编号，要转换
		String bankId = bankCode.length() == 4 ? bankCode : bankCode.length() == 10 ? bankCode.substring(2, 6) : null;
		bankId = JzhBankIdMap.findJzhByFuiouBankCode(bankId);
		AssertUtil.assertNotEmpty(bankId, "BANK_ID_NOT_EXIST");

		JzhRegService.Param param = new JzhRegService.Param();
		param.setMchntTxnSsn(orderNo);
		param.setCustNm(userDO.getTrueName());
		param.setCertifTp("0");
		param.setCertifId(userDO.getPid());
		param.setMobileNo(userDO.getMobile());
		param.setEmail("");
		param.setCityId(cityId);
		param.setParentBankId(bankId);
		param.setCapAcntNo(userBankList.get(0).getBankCardNo());
		param.setPassword(userDO.getLoginPwd().toLowerCase());
		param.setLpassword(userDO.getLoginPwd().toLowerCase());
		param.setRem("");
		param.setBankNm(userBankList.get(0).getBankName());
		JzhRegService.Result result = jzhRegService.post(param);
		AssertUtil.assertNotNull(result, "JZH_OPEN_ERROR");
		AssertUtil.assertTrue("0000".equals(result.getRespCode()), "JZH_" + result.getRespCode() + "_" + result.getRespDesc());

		JzhAccountDO newJzhAccountDO = new JzhAccountDO();
		newJzhAccountDO.setId(uid);
		newJzhAccountDO.setBankNm(param.getBankNm());
		newJzhAccountDO.setCapAcntNm(param.getCapAcntNm());
		newJzhAccountDO.setCapAcntNo(param.getCapAcntNo());
		newJzhAccountDO.setCertifId(param.getCertifId());
		newJzhAccountDO.setCertifTp(param.getCertifTp());
		newJzhAccountDO.setCustNm(param.getCustNm());
		newJzhAccountDO.setEmail(param.getEmail());
		newJzhAccountDO.setParentBankId(param.getParentBankId());
		newJzhAccountDO.setLpassword(param.getLpassword());
		newJzhAccountDO.setPassword(param.getPassword());
		newJzhAccountDO.setMchntTxnSsn(param.getMchntTxnSsn());
		newJzhAccountDO.setMobileNo(param.getMobileNo());
		newJzhAccountDO.setRespDesc(result.getRespDesc());
		newJzhAccountDO.setRespCode(result.getRespCode());
		newJzhAccountDO.setRem(param.getRem());
		newJzhAccountDO.setCityId(param.getCityId());
		AssertUtil.assertTrue(this.create(newJzhAccountDO), "CREATE_JZH_ACCOUNT_DO_FAIL");
		// AssertUtil.assertTrue(userService.updateJzhStatus(uid,
		// "balance_dispose"), "UPDATE_JZH_STATUS_FAIL");
		AssertUtil.assertTrue(userService.updateJzhStatus(uid, "enable"), "UPDATE_JZH_STATUS_FAIL");
		AssertUtil.assertTrue(userService.updateStatus(uid, "enable", "已开通金帐户"), "LOCK_USR_FAIL");

		return true;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Transactional
	@Override
	public BigDecimal add(String uid, BigDecimal amt, String certificateId, String type, String summary) {
		JzhAccountDO accountDO = get(JzhAccountDO.class, uid);
		AssertUtil.assertNotNull(accountDO, "JZH_ACCOUNT_NOT_EXIST");
		AssertUtil.assertTrue(amt != null && amt.compareTo(BigDecimal.ZERO) > 0, "AMT_LESS_ZERO");
		AssertUtil.assertNotNull(certificateId, "CERTIFICATE_ID_IS_EMPTY");
		AssertUtil.assertNotNull(type, "TYPE_IS_EMPTY");
		AssertUtil.assertTrue(accountDO.getBalance() != null && accountDO.getBalance().compareTo(BigDecimal.ZERO) >= 0, "JZH_BALANCE_LESS_ZERO");

		JzhBalanceItemDO itemDO = new JzhBalanceItemDO();
		itemDO.setAccountId(accountDO.getId());
		itemDO.setAmt(amt);
		itemDO.setBalance(accountDO.getBalance().add(amt));
		itemDO.setId(certificateId);
		itemDO.setType(type);
		itemDO.setSummary(summary);
		AssertUtil.assertTrue(jzhBalanceItemService.create(itemDO), "CREATE_BALANCE_ITEM_FAIL");

		Map map = new HashMap();
		map.put("id", accountDO.getId());
		map.put("amt", itemDO.getAmt());
		map.put("balance", itemDO.getBalance());

		AssertUtil.assertTrue(this.updateDao.update("JZH_ACCOUNT.add", map) == 1, "ADD_JZH_ACCOUNT_BALANCE_FAIL");

		return itemDO.getBalance();
	}

	@Override
	public BigDecimal subtract(String uid, BigDecimal amt, String certificateId, String type, String summary) {
		JzhAccountDO accountDO = get(JzhAccountDO.class, uid);
		AssertUtil.assertNotNull(accountDO, "JZH_ACCOUNT_NOT_EXIST");
		AssertUtil.assertTrue(amt != null && amt.compareTo(BigDecimal.ZERO) > 0, "AMT_LESS_ZERO");
		AssertUtil.assertNotNull(certificateId, "CERTIFICATE_ID_IS_EMPTY");
		AssertUtil.assertNotNull(type, "TYPE_IS_EMPTY");
		AssertUtil.assertTrue(accountDO.getBalance() != null && accountDO.getBalance().compareTo(BigDecimal.ZERO) >= 0, "JZH_BALANCE_LESS_ZERO");

		JzhBalanceItemDO itemDO = new JzhBalanceItemDO();
		itemDO.setAccountId(accountDO.getId());
		itemDO.setAmt(amt);
		itemDO.setBalance(accountDO.getBalance().subtract(amt));
		itemDO.setId(certificateId);
		itemDO.setType(type);
		itemDO.setSummary(summary);
		AssertUtil.assertTrue(jzhBalanceItemService.create(itemDO), "CREATE_BALANCE_ITEM_FAIL");

		Map map = new HashMap();
		map.put("id", accountDO.getId());
		map.put("amt", itemDO.getAmt());
		map.put("balance", itemDO.getBalance());

		AssertUtil.assertTrue(this.updateDao.update("JZH_ACCOUNT.subtract", map) == 1, "SUBTRACT_JZH_ACCOUNT_BALANCE_FAIL");

		return itemDO.getBalance();
	}

	@Transactional
	@Override
	public CreateJzhAccountResult createAccount(CreateJzhAccountParam param) {
		AssertUtil.assertNotNull(param, "PARAM_ERROR:参数错误");
		AssertUtil.assertNotEmpty(param.getCityId(), "NEED_CITY_ID:请选择开户行城市");
		AssertUtil.assertNotEmpty(param.getUserId(), "NEED_USER_ID:未指定用户");
		UserDO userDO = this.userService.get(UserDO.class, param.getUserId());
		AssertUtil.assertNotNull(userDO, "USER_NOT_EXIST:用户不存在");
		AssertUtil.assertFalse("enable".equalsIgnoreCase(userDO.getJzhStatus()), "JZH_ACCOUNT_EXIST:用户已开通存管");
		AssertUtil.assertFalse("disable".equalsIgnoreCase(userDO.getJzhStatus()), "JZH_STATUS_DISABLE:您不能自助开通存管");
		AssertUtil.assertTrue("CURRENT_ACCOUNT".equalsIgnoreCase(userDO.gethType()), "USER_NOT_CURRENT_ACCOUNT:用户未开通复利");

		// 开通金账户
		String orderNo = userDO.getMobile() + System.currentTimeMillis() + "";
		String bankCode = null;
		String bankCardCode = null;
		String bankName = null;
		String bankId = null;
		boolean newCard = false;
		boolean isNewUsr = StringUtil.isEmpty(userDO.getTrueName());
		if (StringUtil.isNotEmpty(param.getExistBankId())) {
			UserBankDO userBankDO = userBankService.get(UserBankDO.class, param.getExistBankId());
			AssertUtil.assertNotNull(userBankDO, "BANK_CARD_NOT_EXIST:银行卡不存在");
			AssertUtil.assertTrue(userBankDO.getUserId().equals(param.getUserId()), "BANK_CARD_NOT_MATCH_USER:用户卡不匹配");
			bankCode = userBankDO.getBankCode();
			bankCardCode = userBankDO.getBankCardNo();
			bankName = userBankDO.getBankName();
			// 10位为富友银行编号，要转换
			//bankId = bankCode.length() == 4 ? bankCode : bankCode.length() == 10 ? bankCode.substring(2, 6) : null;
			//bankId = JzhBankIdMap.findJzhByFuiouBankCode(bankId);
			bankId = param.getBankCode();
			AssertUtil.assertNotEmpty(bankId, "BANK_ID_NOT_EXIST");
		} else {
			newCard = true;
			// 新卡或是新用户
			if (isNewUsr) {
				AssertUtil.assertNotEmpty(param.getUserName(), "USER_NAME_EMPTY:请输入姓名");
				AssertUtil.assertNotEmpty(param.getPid(), "PID_EMPTY:请输入身份证号码");
				List<UserDO> userList = userService.findByPid(param.getPid());
				AssertUtil.assertTrue(userList == null || userList.isEmpty(), "PID_USED:该身份证已注册");
			} else {

				AssertUtil.assertTrue(param.getPid().equalsIgnoreCase(userDO.getPid()), "PID_NOT_MATCH:非本人银行卡");
			}
			AssertUtil.assertNotEmpty(param.getUserName(), "USER_NAME_EMPTY:请输入姓名");
			AssertUtil.assertNotEmpty(param.getPid(), "PID_EMPTY:请输入身份证号码");
			AssertUtil.assertNotEmpty(param.getBankCardCode(), "CARD_CODE_EMPTY:请输入银行卡号码");
			AssertUtil.assertNotEmpty(param.getBankCode(), "BANK_CODE_EMPTY:请选择银行");
			AssertUtil.assertNotEmpty(param.getBankName(), "BANK_NAME_EMPTY:请选择银行");
			bankId = param.getBankCode();
			bankCardCode = param.getBankCardCode();
			bankName = param.getBankName();
		}

		JzhRegService.Param jzhParam = new JzhRegService.Param();

		jzhParam.setMchntTxnSsn(orderNo);
		jzhParam.setCustNm(isNewUsr ? param.getUserName() : userDO.getTrueName());
		jzhParam.setCertifTp("0");
		jzhParam.setCertifId(isNewUsr ? param.getPid() : userDO.getPid());
		jzhParam.setMobileNo(userDO.getMobile());
		jzhParam.setEmail("");
		jzhParam.setCityId(param.getCityId());
		jzhParam.setParentBankId(bankId);
		jzhParam.setCapAcntNo(bankCardCode);
		jzhParam.setPassword(userDO.getLoginPwd().toLowerCase());
		jzhParam.setLpassword(userDO.getLoginPwd().toLowerCase());
		jzhParam.setRem("");
		jzhParam.setBankNm(bankName);

		JzhRegService.Result result = jzhRegService.post(jzhParam);
		AssertUtil.assertNotNull(result, "JZH_OPEN_ERROR:开通失败");
		AssertUtil.assertTrue("0000".equals(result.getRespCode()), "JZH_" + result.getRespCode() + ":" + result.getRespDesc());

		// 本地金账户数据
		JzhAccountDO newJzhAccountDO = new JzhAccountDO();
		newJzhAccountDO.setId(userDO.getId());
		newJzhAccountDO.setBankNm(jzhParam.getBankNm());
		newJzhAccountDO.setCapAcntNm(jzhParam.getCapAcntNm());
		newJzhAccountDO.setCapAcntNo(jzhParam.getCapAcntNo());
		newJzhAccountDO.setCertifId(jzhParam.getCertifId());
		newJzhAccountDO.setCertifTp(jzhParam.getCertifTp());
		newJzhAccountDO.setCustNm(jzhParam.getCustNm());
		newJzhAccountDO.setEmail(jzhParam.getEmail());
		newJzhAccountDO.setParentBankId(jzhParam.getParentBankId());
		newJzhAccountDO.setLpassword(jzhParam.getLpassword());
		newJzhAccountDO.setPassword(jzhParam.getPassword());
		newJzhAccountDO.setMchntTxnSsn(jzhParam.getMchntTxnSsn());
		newJzhAccountDO.setMobileNo(jzhParam.getMobileNo());
		newJzhAccountDO.setRespDesc(result.getRespDesc());
		newJzhAccountDO.setRespCode(result.getRespCode());
		newJzhAccountDO.setRem(jzhParam.getRem());
		newJzhAccountDO.setCityId(jzhParam.getCityId());
		AssertUtil.assertTrue(this.create(newJzhAccountDO), "CREATE_JZH_ACCOUNT_DO_FAIL");
		AssertUtil.assertTrue(userService.updateJzhStatus(userDO.getId(), "enable"), "UPDATE_JZH_STATUS_FAIL");
		AssertUtil.assertTrue(userService.updateStatus(userDO.getId(), "enable", "已开通金帐户"), "LOCK_USR_FAIL");
		// 新用户就算认证成功
		if (isNewUsr) {
			userDO = userService.get(UserDO.class, userDO.getId());
			userDO.setTrueName(param.getUserName());
			userDO.setPid(param.getPid());
			AssertUtil.assertTrue(userService.updateSkipCheckOwner(userDO), "USER_UPDATE_FAIL:更新认证失败");
		}
		CreateJzhAccountResult accResult = new CreateJzhAccountResult();
		return accResult;
	}
}
